<?php

/*
class Router, container routing requests to other components
Copyright (C) 2011  Petr Čermák

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

require_once 'View.php';
require_once 'Checker.php';
require_once 'Container.php';

class Router extends Container{

    private $pageString = "p";
    private $defaultPage = null;
    private $lastComponent = null;
    private $lastPage = null;

    public function getPageString(){return $this->pageString;}

    //public function getLastComponent(){return $this->lastComponent;}

    public function processRequest(){
        $view = $this->getView();
        if($view != null){
            $view->setValue("content", $this->createContent());
            parent::processRequest();
        }
        else{
            $this->includeContent();
            parent::processRequest();
        }
    }

    public function createOutput(){
        ob_start();
        $this->processRequest();
        $content = ob_get_contents();
        ob_end_clean();
        return $content;
    }

    public function createPageAddress($page, $param = array()){
        $this->checkPage($page);
        if($this->getOwner() == null)$address = $this->createTopPageAddress($page);
        else{
            $owner = $this;
            do{$owner = $owner->getOwner();}
            while(!($owner == null || $owner instanceof Router));
            if($owner == null)$address = $this->createTopPageAddress($page);
            else $address = $owner->createPageAddress($this->getName()).
                            "&amp;$this->pageString=$page";
        }
        foreach($param as $name => $value)
            if($value != null)$address .= "&amp;$name=$value";
        return $address;
    }

    private function createTopPageAddress($page){
        $address = $_SERVER['PHP_SELF']."?$this->pageString=$page";
        $delParam = $this->getDeletableParameters();
        $urlParam = Application::getValidUrlParameters();
        foreach($urlParam as $name => $value)
            if(!in_array($name, $delParam) && $name != $this->pageString)
                $address .= "&amp;$name=$value";
        return $address;
    }

    public function setDefaultPage($defaultPage){
        Checker::checkString($defaultPage);
        $this->defaultPage = $defaultPage;
    }

    public function setPageString($pageString){
        Checker::checkString($pageString);
        $this->pageString = $pageString;
    }

    public function getUsedParameters(){
        $param = $this->getDeletableParameters() + parent::getUsedParameters();
        $param[] = $this->pageString;
        return $param;
    }

    private function getDeletableParameters(){
        if($this->lastComponent == null ||
           $this->lastComponent instanceof View ||
           $this->lastComponent->isPreservationEnabled())
            return array();
        else return $this->lastComponent->getUsedParameters();
    }

    private function renderPage($page){
        $this->checkPage($page);
        $component = $this->getComponent($page);
        if($component != null && $component->isEnabled()){
            $this->lastComponent = $component;
            //$component->initialize();
            $component->processRequest();
        }
    }

    private function createContent(){
        ob_start();
        $this->includeContent();
        $content = ob_get_contents();
        ob_end_clean();
        return $content;
    }

    private function includeContent(){
        if(isset($_GET[$this->pageString])){
            $page = $_GET[$this->pageString];
            if(is_string($page) && trim($page) != "" && $this->hasComponent($page))
                $this->renderPage($_GET[$this->pageString]);
            else if($this->defaultPage != null)
                $this->renderPage($this->defaultPage);
        }
        else if($this->defaultPage != null)
            $this->renderPage($this->defaultPage);
    }

    private function updateComponent($page){
        $this->lastComponent = $this->getComponent($page);
        //$this->lastComponent->initialize();
        if($this->lastComponent instanceof Router)
            $this->lastComponent->updateLastComponent();
    }

    public function updateLastComponent(){
        if(isset($_GET[$this->pageString])){
            $page = $_GET[$this->pageString];
            if(is_string($page) && trim($page) != "" &&
               $this->hasComponent($page)){
               $this->updateComponent($page);
            }
            else if($this->defaultPage != null)
                $this->updateComponent($this->defaultPage);
        }
        else if($this->defaultPage != null)
            $this->updateComponent($this->defaultPage);
    }

    // --- error checking

    private function checkPage($page){
        if(Checker::isEnabled() && (!is_string($page) || trim($page) == "" || !$this->hasComponent($page)))
            throw new InvalidArgumentException("invalid page name", null, null);
    }

}
?>
